import java.util.ArrayList;

public abstract class Piece {
	private PlayingField pf;
	private Board board;
	private Square sq;
	protected int side;	//side 1: LOWER; side 2: higher
	protected boolean hasMoved;
	private boolean isFrozen;
	protected ArrayList<Square> moves;
	protected ArrayList<Square> capts;
	
	protected abstract ArrayList<Square> getAvailableMoves();
	protected abstract ArrayList<Square> getAvailableCapts();
	
	public Piece(int s){
		hasMoved = false;
		moves = new ArrayList<Square>();
		capts = new ArrayList<Square>();
		side = s;
	}
	
	public PlayingField getPF() {
		return pf;
	}
	
	public void setPF(PlayingField pf) {
		this.pf = pf;
	}
	
	public Board getBoard() {
		return board;
	}
	
	public void setBoard(Board board) {
		this.board = board;
	}
	
	public Square getSquare() {
		return sq;
	}
	
	public void setSquare(Square square) {
		this.sq = square;
	}
	
	public boolean isFrozen() {
		return isFrozen;
	}
	
	public void freeze() {
		isFrozen = true;
	}
	
	public void unfreeze() {
		isFrozen = false;
	}
	
	public int getSide() {
		return side;
	}
	
	public void setSide(int side) {
		this.side = side;
	}
	
	/* 1. Is dest valid?
	 * 2. Is dest contained in the ArrayList?
	 * 3. Is dest not occupied?
	 * 4. Is the moving piece not frozen?*/
	public boolean canMoveTo(Square dest){
		return dest.isValid()
			&& getAvailableMoves().contains(dest)
			&& !dest.isOccupied()
			&& !isFrozen();
	}
	
	/* 1. Is dest valid?
	 * 2. Is dest contained in the ArrayList?
	 * 3. Is dest occupied by a Piece and is it an opposing piece?
	 * 4. Is the moving piece not frozen?*/
	public boolean canCaptTo(Square dest) {
		return dest.isValid()
			&& getAvailableCapts().contains(dest)
			&& (dest.getPiece() != null && dest.getPiece().getSide() != side)
			&& !isFrozen();
	}
	
	public boolean moveTo(Square dest) {
		if (canMoveTo(dest) || canCaptTo(dest)){
			sq.removePiece();
			setSquare(dest);
			sq.setPiece(this);
			System.out.println(sq.getPiece());
			if(sq.getBoard().getLevel() == 1 && sq.getFarSquare(Square.DOWN, 1).getPiece() instanceof Basilisk) {
				freeze();
			}
			hasMoved = true;
			return true;
		}
		return false;
	}
	
	public boolean captTo(Square dest) {
		if(canCaptTo(dest)) {
			setSquare(dest);
			//INSERT CODE TO MOVE "PHYSICAL" PIECE TO DEST!
			return true;
		}
		return false;
	}
	
	public void putSelfInBoard(Board b, Square s) {
		if (b != null) {
			removeSelfFromBoard();
		}
	}
	
	public void removeSelfFromBoard() {
		if (board == null) {
			throw new IllegalStateException("This piece is not on a board.");
		}
		if (!board.getPiece(sq.getCol(), sq.getRow()).equals(this)){
			throw new IllegalStateException("The location specified does not contain this piece.");
		}
		sq = null;
		//INSERT CODE TO REMOVE "PHYSICAL" PIECE FROM BOARD!
	}
}
